// ==UserScript==
// @name         疾控学习网
// @namespace    https://service.cpma.org.cn/edu/
// @version      20241126
// @description  加速大学习完成进程
// @author       Shine
// @match        https://service.cpma.org.cn/edu/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// ==/UserScript==

(function() {
    'use strict';


    // URL 变动时
    function onUrlChange() {

        const practicePageRegex = /^https:\/\/service\.cpma\.org\.cn\/edu\/practice\/.+/;
        const examPageRegex = /^https:\/\/service\.cpma\.org\.cn\/edu\/exam\/onlineExam\/.+/;
        const courseDetailPageRegex = /^https:\/\/service\.cpma\.org\.cn\/edu\/course\/courseDetails\/.+/;
        const onlineStudyPageRegex = /^https:\/\/service\.cpma\.org\.cn\/edu\/course\/onlineStudy\/.+/;
        const examDetailPageRegex = /^https:\/\/service\.cpma\.org\.cn\/edu\/exam\/userexamresult\/ExamDetail\/.+/;


        class IndexedDBHelper {
            constructor(dbName, storeName, version = 1) {
              this.dbName = dbName;
              this.storeName = storeName;
              this.version = version;
              this.db = null;
            }

            // 打开数据库
            openDB() {
              return new Promise((resolve, reject) => {
                const request = indexedDB.open(this.dbName, this.version);

                request.onupgradeneeded = (event) => {
                  this.db = event.target.result;
                  if (!this.db.objectStoreNames.contains(this.storeName)) {
                    this.db.createObjectStore(this.storeName, { keyPath: 'id', autoIncrement: true });
                  }
                };

                request.onsuccess = (event) => {
                  this.db = event.target.result;
                  console.log('数据库打开成功');
                  resolve(this.db);
                };

                request.onerror = (event) => {
                  console.error('数据库打开失败', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            // 添加对象
            addObject(obj) {
              return new Promise((resolve, reject) => {
                const transaction = this.db.transaction([this.storeName], 'readwrite');
                const objectStore = transaction.objectStore(this.storeName);
                const request = objectStore.add(obj);

                request.onsuccess = () => {
                  console.log('对象添加成功:', obj);
                  resolve(obj);
                };

                request.onerror = (event) => {
                  console.error('对象添加失败', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            // 获取对象
            getObject(id) {
              return new Promise((resolve, reject) => {
                const transaction = this.db.transaction([this.storeName], 'readonly');
                const objectStore = transaction.objectStore(this.storeName);
                const request = objectStore.get(id);

                request.onsuccess = (event) => {
                  const result = event.target.result;
                  if (result) {
                    console.log('对象读取成功:', result);
                    resolve(result);
                  } else {
                    console.log('对象未找到');
                    resolve(null);
                  }
                };

                request.onerror = (event) => {
                  console.error('对象读取失败', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            // 更新对象
            updateObject(obj) {
              return new Promise((resolve, reject) => {
                const transaction = this.db.transaction([this.storeName], 'readwrite');
                const objectStore = transaction.objectStore(this.storeName);
                const request = objectStore.put(obj);

                request.onsuccess = () => {
                  console.log('对象更新成功:', obj);
                  resolve(obj);
                };

                request.onerror = (event) => {
                  console.error('对象更新失败', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            // 更新多个对象
            updateObjects(objects) {
              return new Promise((resolve, reject) => {
                const transaction = this.db.transaction([this.storeName], 'readwrite');
                const objectStore = transaction.objectStore(this.storeName);

                objects.forEach(obj => {
                  const request = objectStore.put(obj);

                  request.onsuccess = () => {
                    console.log('对象更新成功:', obj);
                  };

                  request.onerror = (event) => {
                    console.error('对象更新失败', event.target.error);
                  };
                });

                transaction.oncomplete = () => {
                  console.log('所有对象更新完成');
                  resolve(objects);
                };

                transaction.onerror = (event) => {
                  console.error('事务失败:', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            // 删除对象
            deleteObject(id) {
              return new Promise((resolve, reject) => {
                const transaction = this.db.transaction([this.storeName], 'readwrite');
                const objectStore = transaction.objectStore(this.storeName);
                const request = objectStore.delete(id);

                request.onsuccess = () => {
                  console.log('对象删除成功:', id);
                  resolve(id);
                };

                request.onerror = (event) => {
                  console.error('对象删除失败', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            // 获取所有对象
            getAllItems() {
              return new Promise((resolve, reject) => {
                const transaction = this.db.transaction([this.storeName], 'readonly');
                const objectStore = transaction.objectStore(this.storeName);
                const request = objectStore.openCursor();

                const items = [];

                request.onsuccess = (event) => {
                  const cursor = event.target.result;
                  if (cursor) {
                    items.push(cursor.value);
                    cursor.continue();
                  } else {
                    console.log('所有对象读取成功:', items);
                    resolve(items);
                  }
                };

                request.onerror = (event) => {
                  console.error('对象读取失败', event.target.error);
                  reject(event.target.error);
                };
              });
            }

            findByContent(searchString) {
                return new Promise((resolve, reject) => {
                  const transaction = this.db.transaction([this.storeName], 'readonly');
                  const objectStore = transaction.objectStore(this.storeName);
                  const request = objectStore.openCursor();

                  const foundItems = [];

                  request.onsuccess = (event) => {
                    const cursor = event.target.result;
                    if (cursor) {
                      const record = cursor.value;
                      // 检查记录的"content"字段是否包含searchString
                      if (record.content && record.content.includes(searchString)) {
                        foundItems.push(record); // 符合条件的对象
                      }
                      cursor.continue(); // 继续游标
                    } else {
                      // 没有更多记录，返回结果
                      resolve(foundItems);
                    }
                  };

                  request.onerror = (event) => {
                    console.error('查找失败:', event.target.error);
                    reject(event.target.error);
                  };
                });
              }
        }
        const dbHelper = new IndexedDBHelper('MyDatabase', 'Cpma');
        let nextQuestionInterval = 500;
        let actionButton;

        if (window.location.href != 'https://service.cpma.org.cn/edu/home'){
            const clearBlock = setInterval(() => {

                try {
                    const menuElement = document.querySelectorAll('ul.ant-menu.ant-menu-root.ant-menu-inline.ant-menu-dark.jeecg-basic-menu.justify-center')[0];
                    if (menuElement) {
                        menuElement.remove();
                        clearInterval(clearBlock);
                    }
                } catch (e) {
                    // 静默处理错误
                    console.error('清除菜单栏失败:', e);
                    clearInterval(clearBlock);
                }

                //document.querySelectorAll('header.ant-layout-header.jeecg-layout-header')[0].remove();
                //document.querySelectorAll('div .scrollbar__view')[0].remove();
                //document.querySelectorAll('div .scrollbar__view')[0].remove();
            }, 100);

        }

        if (practicePageRegex.test(window.location.href)) {
            // 在练习页面获取全部题目

            // 捕获网页原有的XMLHttpRequest，克隆和重写其open、send、setRequestHeader方法，以便捕获500条题目
            let capturedRequest = null;
            const originalOpen = XMLHttpRequest.prototype.open;
            const originalSend = XMLHttpRequest.prototype.send;
            const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;

            XMLHttpRequest.prototype.open = function(method, url) {
                this.requestMethod = method;
                this.requestUrl = url;
                this.requestHeaders = {};
                originalOpen.apply(this, arguments);
            };

            XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
                this.requestHeaders[header] = value;
                originalSetRequestHeader.apply(this, arguments);
            };

            XMLHttpRequest.prototype.send = function(body) {
                const xhr = this;
                if (xhr.requestUrl.includes('/listQuestionByMode')) {
                    xhr.addEventListener('load', function() {
                        capturedRequest = {
                            method: xhr.requestMethod,
                            url: xhr.responseURL.replace(/([?&])pageSize=\d+/, '$1pageSize=500'),
                            requestBody: body,
                            requestHeaders: xhr.requestHeaders
                        };
                        // console.log('Captured request:', capturedRequest);
                        replayRequest();

                    });
                }
                originalSend.apply(xhr, arguments);
            };

            // Function to replay the request
            function replayRequest() {
                if (!capturedRequest) return;

                const headers = capturedRequest.requestHeaders || {};
                headers['Content-Type'] = 'application/json';

                let bodyToSend = capturedRequest.requestBody;
                if (typeof bodyToSend === 'string') {
                    try {
                        bodyToSend = JSON.parse(bodyToSend);
                    } catch (e) {
                        console.error('Failed to parse request body as JSON. Sending as is.');
                    }
                }

                // console.log('Replaying request:', { method: capturedRequest.method, url: capturedRequest.url, headers: headers, body: bodyToSend });

                GM_xmlhttpRequest({
                    method: capturedRequest.method,
                    url: capturedRequest.url,
                    //data: JSON.stringify(bodyToSend),
                    headers: headers,
                    onload: function(response) {
                        // console.log('Request replayed. Response:', response);
                        try {
                            const responseData = JSON.parse(response.responseText);
                            // console.log(responseData.result.records)

                            dbHelper.openDB().then(() => {
                                dbHelper.updateObjects(responseData.result.records);
                            });

                            setTimeout(() => {
                                window.close();
                            }, 1000);

                        } catch (e) {
                            console.error('Failed to parse response:', e);
                            setTimeout(replayRequest, 5000);
                        }
                    },
                    onerror: function(error) {
                        console.error('Request replay failed:', error);
                        setTimeout(replayRequest, 500);
                    }
                });
            }

            const clickPracticeEntry = setInterval(() => {
                const practiceEntry = document.querySelectorAll('div.card-wrap')[0];
                if (practiceEntry) {
                    practiceEntry.click();
                    clearInterval(clickPracticeEntry);
                }
            }, 1000);

        } else if (examPageRegex.test(window.location.href)){
            // 在考试页面作答

            let skipQuestions = 0;
            setTimeout(() => {
                const examLoop = setInterval(async () => {
                    const mainContent = document.querySelectorAll('div.content')[0].innerText;

                    const correctContents = await findAnswers(mainContent);
                    if (skipQuestions >= 3) {
                        document.querySelectorAll('div .ant-btn.ant-btn-primary')[1].click();
                        setTimeout(() => {
                            document.querySelectorAll('div .ant-btn.ant-btn-primary')[2].click();
                        }, 300);
                    }
                    correctContents.forEach(content => {
                        const divs = document.querySelectorAll('div.content');
                        divs.forEach(div => {
                            if (div.innerText.trim() === content) {
                                div.click();
                                // console.log(`Found div with content: "${content}"`);
                                // 可以在这里对找到的 div 进行进一步操作，比如添加 class
                                // div.classList.add('highlight');
                            }
                        });
                    });
                    setTimeout(() => {
                        try{
                            document.querySelectorAll('div .ant-btn.ant-btn-warning')[0].click();
                        } catch(e) {
                            document.querySelectorAll('div .ant-btn.ant-btn-primary')[1].click();
                            setTimeout(() => {
                                document.querySelectorAll('div .ant-btn.ant-btn-primary')[2].click();
                            }, 300);

                        }
                    }, 300);
                    /*const practiceEntry = document.querySelectorAll('div.card-wrap')[0];
                    if (practiceEntry) {
                        practiceEntry.click();
                        clearInterval(examLoop);
                    }
                        */
                }, 2000);
            }, 3000);


            async function findAnswers(content2find){
                try {

                    await dbHelper.openDB();
                    const foundItems = await dbHelper.findByContent(content2find);
                    console.log('查找到的对象:', foundItems);
                    console.log(foundItems[0].answerList);
                    const answerList = foundItems[0].answerList
                    const correctContents = answerList
                        .filter(item => item.isRight)
                        .map(item => item.content);
                    console.log(correctContents);
                    return correctContents;


                } catch (error) {
                    console.error('Error finding answers:', error);
                    skipQuestions++;
                    return [];
                }
            }
        } else if (onlineStudyPageRegex.test(window.location.href)){

            console.log("进入在线学习页面");
            // 捕获网页原有的XMLHttpRequest，克隆和重写其open、send、setRequestHeader方法，以便捕获500条题目
            // 仅重放 POST 并捕获响应内容
            let success = false;
            let capturedRequest = null;
            let originalOpen = XMLHttpRequest.prototype.open;
            let originalSend = XMLHttpRequest.prototype.send;
            let originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;

            XMLHttpRequest.prototype.open = function(method, url) {
                this.requestMethod = method;
                this.requestUrl = url;
                this.requestHeaders = {};
                originalOpen.apply(this, arguments);
            };

            XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
                this.requestHeaders[header] = value;
                originalSetRequestHeader.apply(this, arguments);
            };

            XMLHttpRequest.prototype.send = function(body) {
                const xhr = this;
                if (xhr.requestUrl.includes('/getCourseStudyProcess')) {
                    xhr.addEventListener('load', function() {

                        try {

                            const response = JSON.parse(xhr.responseText);
                            if (response.success && response.result && response.result.length > 0) {
                                const { userId, courseCatalogId } = response.result[0];
                                // sessionStorage.setItem('cpmaUserId', userId);
                                // sessionStorage.setItem('cpmaCatalogId', courseCatalogId);
                                const courseId = window.location.href.match(/\/onlineStudy\/([^/?]+)/)[1];
                                console.log('获取到courseId:', courseId);
                                console.log('获取到userId:', userId);
                                console.log('获取到courseCatalogId:', courseCatalogId);
                                capturedRequest = {
                                    method: xhr.requestMethod,
                                    url: xhr.responseURL.replace(/getCourseStudyProcess\?.*$/, "calcStudyProcess"),
                                    requestBody: { courseId: courseId, catalogId: courseCatalogId, userId: userId, viewProcess: 1 },
                                    requestHeaders: xhr.requestHeaders
                                };
                                // console.log('Captured request:', capturedRequest);
                                replayRequest();
                                setTimeout(() => {
                                    localStorage.setItem('refreshCourseDetailPage', true);
                                    success = true;
                                    history.back(); // 或者 window.history.back();
                                    // window.location.href = window.location.href + '?t=' + new Date().getTime();
                                }, 500);

                            }
                        } catch (e) {
                            console.error('解析响应失败:', e);
                        }

                    });
                }
                originalSend.apply(xhr, arguments);
            };

            // Function to replay the request
            function replayRequest() {
                if (!capturedRequest) return;

                const headers = capturedRequest.requestHeaders || {};
                headers['Content-Type'] = 'application/json';

                let bodyToSend = capturedRequest.requestBody;
                if (typeof bodyToSend === 'string') {
                    try {
                        bodyToSend = JSON.parse(bodyToSend);
                    } catch (e) {
                        console.error('Failed to parse request body as JSON. Sending as is.');
                    }
                }

                // console.log('Replaying request:', { method: capturedRequest.method, url: capturedRequest.url, headers: headers, body: bodyToSend });

                GM_xmlhttpRequest({
                    method: 'POST',
                    url: capturedRequest.url,
                    data: JSON.stringify(bodyToSend),
                    headers: headers,
                    onload: function(response) {
                        //console.log('Request replayed. Response:', response);
                        try {

                            const responseData = JSON.parse(response.responseText);
                            console.log(responseData)

                        } catch (e) {
                            console.error('Failed to parse response:', e);
                            setTimeout(replayRequest, 5000);
                        }
                    },
                    onerror: function(error) {
                        console.error('Request replay failed:', error);
                        setTimeout(replayRequest, 5000);
                    }
                });
            }
            setTimeout(() => {
                // history.back(); // 或者 window.history.back();
                if (!success) {
                    window.location.href = window.location.href + '?t=' + new Date().getTime();
                }
            }, 10000);

        } else if (courseDetailPageRegex.test(window.location.href)){

            console.log("进入课程详情页面");
            // 捕获网页原有的XMLHttpRequest，克隆和重写其open、send、setRequestHeader方法，以便捕获500条题目
            let examId = null;
            let capturedRequest = null;
            const originalOpen = XMLHttpRequest.prototype.open;
            const originalSend = XMLHttpRequest.prototype.send;
            const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;

            XMLHttpRequest.prototype.open = function(method, url) {
                this.requestMethod = method;
                this.requestUrl = url;
                this.requestHeaders = {};
                originalOpen.apply(this, arguments);
            };

            XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
                this.requestHeaders[header] = value;
                originalSetRequestHeader.apply(this, arguments);
            };

            XMLHttpRequest.prototype.send = function(body) {
                const xhr = this;
                if (xhr.requestUrl.includes('/getCourseStudyDetail')) {
                    xhr.addEventListener('load', function() {

                        const response = JSON.parse(xhr.responseText);
                        examId = response.result.examId;
                        capturedRequest = {
                            method: xhr.requestMethod,
                            url: 'https://service.cpma.org.cn/stage-api/edu/exam-boot/userExamResult/examScore?examId=' + examId,
                            requestBody: body,
                            requestHeaders: xhr.requestHeaders
                        };
                        //console.log('Captured request:', capturedRequest);
                        replayRequest();

                    });
                }
                originalSend.apply(xhr, arguments);
            };

            // Function to replay the request
            function replayRequest() {
                if (!capturedRequest) return;

                const headers = capturedRequest.requestHeaders || {};
                headers['Content-Type'] = 'application/json';

                let bodyToSend = capturedRequest.requestBody;
                if (typeof bodyToSend === 'string') {
                    try {
                        bodyToSend = JSON.parse(bodyToSend);
                    } catch (e) {
                        console.error('Failed to parse request body as JSON. Sending as is.');
                    }
                }

                // console.log('Replaying request:', { method: capturedRequest.method, url: capturedRequest.url, headers: headers, body: bodyToSend });

                GM_xmlhttpRequest({
                    method: capturedRequest.method,
                    url: capturedRequest.url,
                    //data: JSON.stringify(bodyToSend),
                    headers: headers,
                    onload: function(response) {
                        //console.log('Request replayed. Response:', response);
                        try {
                            const responseData = JSON.parse(response.responseText);

                            if (responseData.result == null) {

                                const clickExamTab = setInterval(() => {
                                    const tab0 = document.querySelector('#rc-tabs-0-tab-courseExam');
                                    const tab1 = document.querySelector('#rc-tabs-1-tab-courseExam');

                                    if (tab0 || tab1) {
                                        // 移除所有带有 aria-hidden 的元素的 tabindex
                                        document.querySelectorAll('[aria-hidden="true"][tabindex]').forEach(el => {
                                            el.removeAttribute('tabindex');
                                        });

                                        tab0?.click();
                                        tab1?.click();

                                        // 开始检测考试按钮
                                        setTimeout(() => {
                                            // 使用文本内容定位按钮
                                            const examButton = Array.from(document.querySelectorAll('button.ant-btn.ant-btn-primary'))
                                                .find(button => button.textContent.includes('开始考试'));

                                                examButton.click();
                                            }, 3000);

                                            clearInterval(clickExamTab);
                                    }
                                }, 300);
                                setInterval(() => {
                                    if (localStorage.getItem('refreshCourseDetailPage') == 'true'){
                                        localStorage.setItem('refreshCourseDetailPage', false);
                                        location.reload();
                                    }
                                }, 500);
                                // ... existing code ...
                            } else if (responseData.result.passed!=1) {
                                // ... existing code ...
                                const clickExamTab = setInterval(() => {
                                    const tab0 = document.querySelector('#rc-tabs-0-tab-courseExam');
                                    const tab1 = document.querySelector('#rc-tabs-1-tab-courseExam');

                                    if (tab0 || tab1) {
                                        // 移除所有带有 aria-hidden 的元素的 tabindex
                                        document.querySelectorAll('[aria-hidden="true"][tabindex]').forEach(el => {
                                            el.removeAttribute('tabindex');
                                        });

                                        tab0?.click();
                                        tab1?.click();

                                        // 开始检测考试按钮
                                        setTimeout(() => {
                                            // 使用文本内容定位按钮
                                            const examButton = Array.from(document.querySelectorAll('button.ant-btn.ant-btn-primary'))
                                                .find(button => button.textContent.includes('开始考试'));

                                                examButton.click();
                                            }, 3000);

                                            clearInterval(clickExamTab);
                                    }
                                }, 300);
                                setTimeout(() => {
                                    location.reload();
                                }, 50000);

                            } else {
                                setTimeout(() => {
                                    history.back();
                                }, 1000);
                            }



                        } catch (e) {
                            console.error('解析响应失败:', e);


                        }
                    },
                    onerror: function(error) {
                        console.error('Request replay failed:', error);
                        setTimeout(replayRequest, 500);
                    }
                });
            }


            const checkCompletion = setInterval(() => {
                const completionDiv = document.querySelector('div.course_info_wc');
                if (completionDiv) {
                    const completionText = completionDiv.innerText;
                    if (completionText.includes('已完成0个')) {
                        clearInterval(checkCompletion); // 清除interval
                        document.querySelector('button.ant-btn.ant-btn-primary.ant-btn-study')?.click();
                    } else if (completionText.includes('已完成1个')) {
                        clearInterval(checkCompletion);



                    }
                }
            }, 1000);
        } else if (examDetailPageRegex.test(window.location.href)) {
            // 在考试详情页面获取题目

            let capturedRequest = null;
            let isReplayingAutomatically = false;

            // 捕获网页原有的XMLHttpRequest，克隆和重写其open、send、setRequestHeader方法，以便捕获500条题目
            const originalOpen = XMLHttpRequest.prototype.open;
            const originalSend = XMLHttpRequest.prototype.send;
            const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;

            XMLHttpRequest.prototype.open = function(method, url) {
                this.requestMethod = method;
                this.requestUrl = url;
                this.requestHeaders = {};
                originalOpen.apply(this, arguments);
            };

            XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
                this.requestHeaders[header] = value;
                originalSetRequestHeader.apply(this, arguments);
            };

            XMLHttpRequest.prototype.send = function(body) {
                const xhr = this;
                if (xhr.requestUrl.includes('/userExamResultDetail')) {
                    xhr.addEventListener('load', function() {
                        capturedRequest = {
                            method: xhr.requestMethod,
                            url: xhr.responseURL,
                            requestBody: body,
                            requestHeaders: xhr.requestHeaders
                        };
                        // console.log('Captured request:', capturedRequest);
                        if (!isReplayingAutomatically) {
                            startAutomaticReplay();
                        }
                    });
                }
                originalSend.apply(xhr, arguments);
            };

            // Function to start automatic replay
            function startAutomaticReplay() {
                if (isReplayingAutomatically) return;
                isReplayingAutomatically = true;
                // console.log('Starting automatic replay');
                replayRequest();
            }

            // Function to replay the request
            function replayRequest() {
                if (!capturedRequest || !isReplayingAutomatically) return;

                const headers = capturedRequest.requestHeaders || {};
                headers['Content-Type'] = 'application/json';

                let bodyToSend = capturedRequest.requestBody;
                if (typeof bodyToSend === 'string') {
                    try {
                        bodyToSend = JSON.parse(bodyToSend);
                    } catch (e) {
                        console.error('Failed to parse request body as JSON. Sending as is.');
                    }
                }

                // console.log('Replaying request:', { method: capturedRequest.method, url: capturedRequest.url, headers: headers, body: bodyToSend });

                GM_xmlhttpRequest({
                    method: capturedRequest.method,
                    url: capturedRequest.url,
                    //data: JSON.stringify(bodyToSend),
                    headers: headers,
                    onload: function(response) {
                        // console.log('Request replayed. Response:', response);
                        try {
                            const responseData = JSON.parse(response.responseText);
                            let questions = responseData.result.userExamQuestionList;
                            questions.forEach(item => {
                                item.question.content = item.question.content.replace(/<\/?p>/g, '');
                            });
                            const questionList = questions.map(item => item.question);

                            dbHelper.openDB().then(() => {
                                dbHelper.updateObjects(questionList);

                            });
                            localStorage.setItem('refreshCourseDetailPage', true);
                            setTimeout(() => {
                                window.close();
                            }, 1000);


                        } catch (e) {
                            console.error('Failed to parse response:', e);
                            setTimeout(replayRequest, 5000);
                        }
                    },
                    onerror: function(error) {
                        console.error('Request replay failed:', error);
                        setTimeout(replayRequest, 500);
                    }
                });
            }

            const clickPracticeEntry = setInterval(() => {
                const practiceEntry = document.querySelectorAll('div.card-wrap')[0];
                if (practiceEntry) {
                    practiceEntry.click();
                    clearInterval(clickPracticeEntry);
                }
            }, 1000);

        }

    }


    onUrlChange();

    let lastUrl = location.href;
    setInterval(() => {
        if (lastUrl !== location.href) {
            lastUrl = location.href;
            onUrlChange();
        }
    }, 100);

})();